package cuda;


import java.util.HashMap;
import java.util.Map;

import cuda.translation.ITransRules.OpType;

public class Operation {
	public Type left, right;	public String op;
	public Operation(Type left, Type right, String op){
		this.left = left;
		this.right = right;
		this.op = op;
	}
	public boolean equals(Object oper){
		Operation o = (Operation)oper;
		return(o.left == left && o.right == right && o.op.equals(op));
	}
	public int hashCode(){
		return left.toString().length() + right.toString().length() + op.length(); 
	}
	
	public String toString() {
		return "Operation: " + left.toString() + op + right.toString();
	}
}


class OpHandler {
	public OpType operationType;
	public Type returnType; 
	public OpHandler(OpType operationType, Type returnType){
		this.operationType = operationType;
		this.returnType = returnType;
	}

}

class OperMap {
   	static Map<Operation, OpHandler> operMap = new HashMap<Operation, OpHandler>();

   	static {
   		operMap.put(new Operation(Type.MATRIX, Type.MATRIX, "+"), new OpHandler(OpType.MATRIX_PLUS_MATRIX, Type.MATRIX));
	   	operMap.put(new Operation(Type.MATRIX, Type.MATRIX, "-"), new OpHandler(OpType.MATRIX_MINUS_MATRIX, Type.MATRIX));
	   	operMap.put(new Operation(Type.MATRIX, Type.MATRIX, "*"), new OpHandler(OpType.MATRIX_TIMES_MATRIX, Type.MATRIX));
	   	operMap.put(new Operation(Type.VECTOR, Type.VECTOR, "+"), new OpHandler(OpType.VECTOR_PLUS_VECTOR, Type.VECTOR));
	   	operMap.put(new Operation(Type.VECTOR, Type.VECTOR, "-"), new OpHandler(OpType.VECTOR_MINUS_VECTOR, Type.VECTOR));
	   	operMap.put(new Operation(Type.MATRIX, Type.MATRIX, "="), new OpHandler(OpType.MATRIX_COPY, Type.VOID));
	   	operMap.put(new Operation(Type.VECTOR, Type.VECTOR, "="), new OpHandler(OpType.VECTOR_COPY, Type.VOID));
	   	operMap.put(new Operation(Type.VECTOR, Type.VECTOR, "=="), new OpHandler(OpType.VECTOR_EQUAL_VECTOR, Type.BINARY));
	   	operMap.put(new Operation(Type.VECTOR, Type.VECTOR, "~="), new OpHandler(OpType.VECTOR_NEQUAL_VECTOR, Type.BINARY));
	   	operMap.put(new Operation(Type.MATRIX, Type.MATRIX, "=="), new OpHandler(OpType.MATRIX_EQUAL_MATRIX, Type.BINARY));
	   	operMap.put(new Operation(Type.MATRIX, Type.MATRIX, "~="), new OpHandler(OpType.MATRIX_NEQUAL_MATRIX, Type.BINARY));
	   	operMap.put(new Operation(Type.MATRIX, Type.VECTOR, "*"), new OpHandler(OpType.MATRIX_TIMES_VECTOR, Type.VECTOR));
	   	operMap.put(new Operation(Type.VECTOR, Type.MATRIX, "*"), new OpHandler(OpType.VECTOR_TIMES_MATRIX, Type.VECTOR));
	   	operMap.put(new Operation(Type.SCALAR, Type.VECTOR, "*"), new OpHandler(OpType.SCALAR_TIMES_VECTOR, Type.VECTOR));
	   	operMap.put(new Operation(Type.SCALAR, Type.MATRIX, "*"), new OpHandler(OpType.SCALAR_TIMES_MATRIX, Type.MATRIX));
	   
	   	
   	}
	static OpHandler get(Type left, Type right, String o) {
   		Operation op  = new Operation(left, right, o);
   		return operMap.get(op);
   		}
	
   	private OperMap() {}
}